import asyncio
import time
import datetime
import sys
import inspect
import threading
import random

def blocking_func():
    frame_info: inspect.FrameInfo = inspect.stack()[0]
    print(f" thread- {threading.currentThread().ident} in {frame_info.function} begin...")
    time.sleep(5)
    print(f" thread- {threading.currentThread().ident} in {frame_info.function} end")

def callback_done(future):
    print(future)
    future.get_loop().stop()

def main_1():
    loop = asyncio.get_event_loop()
    print(f"主线程-{threading.currentThread().ident}")
    try:
        loop.run_until_complete(loop.run_in_executor(None,blocking_func))
    finally:
        loop.close()

    print("over....")

def main_2():
    loop = asyncio.get_event_loop()
    print(f"主线程-{threading.currentThread().ident}")
    try:
        future = loop.run_in_executor(None,blocking_func)
        #通过回调来终止 循环
        #future.add_done_callback(callback_done)
        #lambda 更简洁
        future.add_done_callback(lambda f: loop.stop())
        loop.run_forever()
    finally:
        if not loop.is_closed():
            loop.close()

    print("over....")


async def coro_func():
    frame_info: inspect.FrameInfo = inspect.stack()[0]
    print(f" thread- {threading.currentThread().ident} in {frame_info.function} begin...")
    await asyncio.sleep(3)
    print(f" thread- {threading.currentThread().ident} in {frame_info.function} end")

def main_3():
    """
    同步阻塞函数 blocking_func 会影响事件循环，可以通过 run_in_executor 将其投递到线程中执行
    """
    loop = asyncio.get_event_loop()
    print(f"主线程-{threading.currentThread().ident} {datetime.datetime.today()}")
    try:
        future = loop.run_in_executor(None, blocking_func)
        tasks = [coro_func() for _ in range(3)]
        loop.run_until_complete(asyncio.gather(future,*tasks))
        # loop.call_soon_threadsafe(blocking_func)
        # loop.run_until_complete(asyncio.gather(*tasks))
    finally:
        try:
            loop.run_until_complete(loop.shutdown_asyncgens())
        finally:
            loop.close()

    print(f"主线程-{threading.currentThread().ident} {datetime.datetime.today()} over")
if __name__ == '__main__':
    main_2()